1 module collie.codec.http.httpwritebuffer;
2 
3 import kiss.container.ByteBuffer;
4 import kiss.net;
5 import kiss.event.core;
6 import kiss.event.task;
7 
8 @trusted abstract class HttpWriteBuffer : StreamWriteBuffer, WriteBuffer
9 {
10 	override abstract size_t write(in ubyte[] data);
11 
12 	override abstract size_t set(size_t pos, in ubyte[] data);
13 
14 	override abstract @property size_t length() const;
15 
16     void setFinalTask(AbstractTask task){
17         _task = task;
18     }
19 
20     override void doFinish() nothrow{
21 		if(_task !is null)
22         	_task.job();
23     }
24     StreamWriteBuffer next(){ return _next; }
25     void next(StreamWriteBuffer v) { _next = v; }
26 
27 private:
28     StreamWriteBuffer _next;
29     AbstractTask _task;
30 }
31 
32 class HTTPByteBuffer(Alloc) : HttpWriteBuffer
33 {
34     import kiss.container.ByteBuffer;
35     import kiss.container.Vector;
36     import std.experimental.allocator.common;
37 
38     alias BufferStore = Vector!(ubyte,Alloc); 
39 
40     static if (stateSize!(Alloc) != 0)
41 	{
42 		this(Alloc alloc)
43 		{
44 			_store = BufferStore(1024,alloc);
45 		}
46 		
47 		@property allocator(){return _store.allocator;}
48 		
49 	} else {
50 		this()
51 		{
52 			_store = BufferStore(1024);
53 		}
54 	}
55 
56 	~this(){
57 		destroy(_store);
58 	}
59 
60     override size_t write(in ubyte[] data)
61 	{
62 		size_t len = _store.length;
63 		()@trusted{_store.insertBack(cast(ubyte[])data);}();
64 		return _store.length - len;
65 	}
66 
67 	override size_t set(size_t pos, in ubyte[] data)
68 	{
69 		import core.stdc.string : memcpy;
70 		if(pos >= _store.length || data.length == 0) return 0;
71 		size_t len = _store.length - pos;
72 		len = len > data.length ? data.length : len;
73 		()@trusted{
74 			ubyte *	ptr = cast(ubyte *)(_store.ptr + pos);
75 			memcpy(ptr, data.ptr, len);
76 		}();
77 		
78 		return len;
79 	}
80 
81     void rest(size_t size){
82 		_rsize = size;
83 	}
84 
85     const(ubyte)[] sendData()  
86     {
87         size_t len = _rsize + 4096;// 一次最大发送4K
88 		len = _store.length < len ? _store.length : len;
89 		auto _data = _store.data();
90 		return _data[_rsize .. len];
91     }
92 
93     bool popSize(size_t size) 
94     {
95         _rsize += size;
96         return _rsize >= _store.length;
97     }
98 
99     override void doFinish() {
100         _store.clear();
101         super.doFinish();
102     }
103 
104 	override size_t length() const{
105 		return _store.length;
106 	}
107 private:
108 	BufferStore _store;
109 	size_t _rsize = 0;
110 }